package com.tank.thread;

import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Random;
import java.util.Set;

import com.tank.entity.Brick;
import com.tank.entity.Bullet;
import com.tank.entity.GameResource;
import com.tank.entity.Iron;
import com.tank.entity.Position;
import com.tank.entity.RobotTank;
import com.tank.entity.Tank;
import com.tank.entity.Water;
import com.tank.response.RobotRouteResponse;
import com.tank.response.TankLocationResponse;
import com.tank.server.handler.TankServer;

import io.netty.channel.Channel;

public class RobotRouteThread extends Thread {
	private GameResource resource;
	private RobotTank robot;
	private Position circleCenterPosition; // 圆心位置
	// private String channelId;
	// private String roomId;
	private Channel channel;
	public boolean stopFlag = false; // 线程结束标识

	public RobotRouteThread(RobotTank robot, GameResource resource, Channel channel) {
		this.robot = robot;
		circleCenterPosition = new Position(robot.getX(), robot.getY());
		this.resource = resource;
		this.channel = channel;
	}

	@Override
	public void run() {
		while (true) {
			if (stopFlag) {
				break;
			}
			// 判断警戒范围内是否有玩家坦克
			for (Tank tank : resource.getPlayerTanks().values()) {
//				if (hEuclidianDistance(circleCenterPosition, tank) < RobotTank.WARNRANGE) {// 判断机器坦克的警戒范围内是否有玩家坦克，如果有，则进行路线规划，没有则随机走动
					// 规划路线
					LinkedList<Tank> routes = findRoute(robot, tank);
					// 机器坦克沿着规划路线走
					for (Tank route : routes) {
						try {
							Thread.sleep(30);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						// 判断：如果沿着规划的路线继续走，会不会跑出警戒范围，如果会，则不走规划的路线
//						if (hEuclidianDistance(circleCenterPosition, route) > RobotTank.WARNRANGE) {
//							break;
//						}
						boolean crash = false; // 机器坦克在规划的路线上发生碰撞
						for (Tank t : resource.getRobotTanks().values()) { // 判断机器坦克是否与其他机器坦克重叠
							if (!robot.getTankId().equals(t.getTankId())) {
								if (robot.Overlap(t) && t.isAlive()) { // 有可能坦克死了，但是子弹仍然显示在界面上，坦克未被移除
									crash = true;
									break;
								}
							}
						}
						for (Tank t : resource.getPlayerTanks().values()) { // 判断机器坦克是否与玩家坦克重叠
							if (robot.Overlap(t) && t.isAlive()) { // 有可能坦克死了，但是子弹仍然显示在界面上，坦克未被移除
								crash = true;
								break;
							}
						}
						if (crash == true) { // 在路径上碰撞的话，不再继续走
							break;
						}
						robot.setX(route.getX());
						robot.setY(route.getY());
						robot.setDirect(route.getDirect());
						// 发送位置信息
						TankLocationResponse tankLocationResponse = new TankLocationResponse();
						tankLocationResponse.setTankId(robot.getTankId());
						tankLocationResponse.setX(robot.getX());
						tankLocationResponse.setY(robot.getY());
						tankLocationResponse.setDirect(robot.getDirect());
						// TankServer.ROOM_CHANNELGROUP.get(roomId).get(channelId).writeAndFlush(tankLocationResponse);
						channel.writeAndFlush(tankLocationResponse);

						for (Tank t : resource.getPlayerTanks().values()) {
							if (Math.abs(t.getX() - robot.getX()) < robot.getWidth() / 2 && t.getY() < robot.getY()) { // 如果机器坦克在下面
								boolean ironFlag = false; // 路径中是否有钢铁的标识
								for (Iron iron : resource.getIrons()) { // 子弹路径上，不会有钢铁
									if (Math.abs(iron.getX() - robot.getX()) < iron.getWidth() / 2
											&& iron.getY() < robot.getY() && iron.getY() > t.getY()) {
										ironFlag = true;
										break;
									}
								}
								if (ironFlag == false) {
									robot.setDirect(Tank.NORTH);
									synchronized (robot.getRemainBulletCount()) {
										if (robot.getRemainBulletCount() > 0) {
											// Bullet bullet = robot.shot();
											// Thread thread = new Thread(new
											// BulletRepaintThread(bullet,
											// robot));
											// thread.start();
										}
									}

								}
							} else if (Math.abs(t.getX() - robot.getX()) < robot.getWidth() / 2
									&& t.getY() > robot.getY()) { // 如果机器坦克在上面
								boolean ironFlag = false; // 路径中是否有钢铁的标识
								for (Iron iron : resource.getIrons()) { // 子弹路径上，不会有钢铁
									if (Math.abs(iron.getX() - robot.getX()) < iron.getWidth() / 2
											&& iron.getY() > robot.getY() && iron.getY() < t.getY()) {
										ironFlag = true;
										break;
									}
								}
								if (ironFlag == false) {
									robot.setDirect(Tank.SOUTH);
									synchronized (robot.getRemainBulletCount()) {
										if (robot.getRemainBulletCount() > 0) {
											// Bullet bullet = robot.shot();
											// Thread thread = new Thread(new
											// BulletRepaintThread(bullet,
											// robot));
											// thread.start();
										}
									}
								}
							} else if (Math.abs(t.getY() - robot.getY()) < robot.getWidth() / 2
									&& t.getX() > robot.getX()) { // 如果机器坦克在左边
								boolean ironFlag = false; // 路径中是否有钢铁的标识
								for (Iron iron : resource.getIrons()) { // 子弹路径上，不会有钢铁
									if (Math.abs(iron.getY() - robot.getY()) < iron.getWidth() / 2
											&& iron.getX() > robot.getX() && iron.getX() < t.getX()) {
										ironFlag = true;
										break;
									}
								}
								if (ironFlag == false) {
									robot.setDirect(Tank.EAST);
									synchronized (robot.getRemainBulletCount()) {
										if (robot.getRemainBulletCount() > 0) {
											// Bullet bullet = robot.shot();
											// Thread thread = new Thread(new
											// BulletRepaintThread(bullet,
											// robot));
											// thread.start();
										}
									}
								}
							} else if (Math.abs(t.getY() - robot.getY()) < robot.getWidth() / 2
									&& t.getX() < robot.getX()) { // 如果机器坦克在右边
								boolean ironFlag = false; // 路径中是否有钢铁的标识
								for (Iron iron : resource.getIrons()) { // 子弹路径上，不会有钢铁
									if (Math.abs(iron.getY() - robot.getY()) < iron.getWidth() / 2
											&& iron.getX() < robot.getX() && iron.getX() > t.getX()) {
										ironFlag = true;
										break;
									}
								}
								if (ironFlag == false) {
									robot.setDirect(Tank.WEST);
									synchronized (robot.getRemainBulletCount()) {
										if (robot.getRemainBulletCount() > 0) {
											// Bullet bullet = robot.shot();
											// Thread thread = new Thread(new
											// BulletRepaintThread(bullet,
											// robot));
											// thread.start();
										}
									}
								}
							}
						}
					}
				}
			}

//			// 如果在警戒范围内没有玩家坦克,随机移动
//			int direct = (int) (Math.random() * 4); // 随机选择移动方向
//			int step = 0;
//			// 如果在接下来的4步没有发生碰撞，并且没有走出警戒范围
//			while (step < 10) {
//				Tank nextPosition = new Tank(robot.getX(), robot.getY() - robot.getSpeed(), direct, "");
//				switch (direct) {
//				case Tank.NORTH:
//					nextPosition.setY(robot.getY() - robot.getSpeed());
//					break;
//				case Tank.SOUTH:
//					nextPosition.setY(robot.getY() + robot.getSpeed());
//					break;
//				case Tank.WEST:
//					nextPosition.setX(robot.getX() - robot.getSpeed());
//					break;
//				case Tank.EAST:
//					nextPosition.setX(robot.getX() + robot.getSpeed());
//					break;
//				}
//				List<Brick> bricks = resource.getBricks();
//				List<Water> waters = resource.getWaters();
//				List<Iron> irons = resource.getIrons();
//				for (int j = 0; j < bricks.size(); j++) { // 判断我的坦克是否与砖块重叠
//					if (nextPosition.Overlap(bricks.get(j)) == true) {
//						nextPosition.setCrash(true);
//						break;
//					}
//				}
//				for (int j = 0; j < irons.size(); j++) { // 判断我的坦克是否与铁块重叠
//					if (nextPosition.Overlap(irons.get(j)) == true) {
//						nextPosition.setCrash(true);
//						break;
//					}
//				}
//				for (int j = 0; j < waters.size(); j++) { // 判断我的坦克是否与河流重叠
//					if (nextPosition.Overlap(waters.get(j)) == true) {
//						nextPosition.setCrash(true);
//						break;
//					}
//				}
//				for (Tank t : resource.getRobotTanks().values()) { //
//					// 判断机器坦克是否与其他机器坦克重叠
//					if (!robot.getTankId().equals(t.getTankId())) {
//						if (nextPosition.Overlap(t) && t.isAlive()) { //
//							// 有可能坦克死了，但是子弹仍然显示在界面上，坦克未被移除
//							nextPosition.setCrash(true);
//							break;
//						}
//					}
//				}
//				for (Tank t : resource.getPlayerTanks().values()) { //
//					// 判断机器坦克是否与玩家坦克重叠
//					if (nextPosition.Overlap(t) && t.isAlive()) { //
//						// 有可能坦克死了，但是子弹仍然显示在界面上，坦克未被移除
//						nextPosition.setCrash(true);
//						break;
//					}
//				}
//				// 不会发生碰撞，并且不会跑出警戒范围
//				if (!nextPosition.isCrash()
//						&& hEuclidianDistance(circleCenterPosition, nextPosition) < RobotTank.WARNRANGE) {
//					robot.setDirect(direct);
//					robot.setX(nextPosition.getX());
//					robot.setY(nextPosition.getY());
//					// 发送位置信息
//					TankLocationResponse tankLocationResponse = new TankLocationResponse();
//					tankLocationResponse.setTankId(robot.getTankId());
//					tankLocationResponse.setX(robot.getX());
//					tankLocationResponse.setY(robot.getY());
//					tankLocationResponse.setDirect(robot.getDirect());
//					channel.writeAndFlush(tankLocationResponse);
//					try {
//						Thread.sleep(30);
//					} catch (InterruptedException e) {
//						e.printStackTrace();
//					}
//				} else {
//					break;
//				}
//			}

//		}
	}

	public void drawRoute(LinkedList<Tank> routes,Tank tank) {

		if (hEuclidianDistance(circleCenterPosition, tank) < RobotTank.WARNRANGE) {// 判断机器坦克的警戒范围内是否有玩家坦克，如果有，则进行路线规划，没有则随机走动
			// 机器坦克沿着规划路线走
			for (Tank route : routes) {
				try {
					Thread.sleep(30);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				// 判断：如果沿着规划的路线继续走，会不会跑出警戒范围，如果会，则不走规划的路线
				if (hEuclidianDistance(circleCenterPosition, route) > RobotTank.WARNRANGE) {
					break;
				}
				boolean crash = false; // 机器坦克在规划的路线上发生碰撞
				for (Tank t : resource.getRobotTanks().values()) { // 判断机器坦克是否与其他机器坦克重叠
					if (!robot.getTankId().equals(t.getTankId())) {
						if (robot.Overlap(t) && t.isAlive()) { // 有可能坦克死了，但是子弹仍然显示在界面上，坦克未被移除
							crash = true;
							break;
						}
					}
				}
				for (Tank t : resource.getPlayerTanks().values()) { // 判断机器坦克是否与玩家坦克重叠
					if (robot.Overlap(t) && t.isAlive()) { // 有可能坦克死了，但是子弹仍然显示在界面上，坦克未被移除
						crash = true;
						break;
					}
				}
				if (crash == true) { // 在路径上碰撞的话，不再继续走
					break;
				}
				robot.setX(route.getX());
				robot.setY(route.getY());
				robot.setDirect(route.getDirect());
				// 发送位置信息
				TankLocationResponse tankLocationResponse = new TankLocationResponse();
				tankLocationResponse.setTankId(robot.getTankId());
				tankLocationResponse.setX(robot.getX());
				tankLocationResponse.setY(robot.getY());
				tankLocationResponse.setDirect(robot.getDirect());
				// TankServer.ROOM_CHANNELGROUP.get(roomId).get(channelId).writeAndFlush(tankLocationResponse);
				channel.writeAndFlush(tankLocationResponse);

				for (Tank t : resource.getPlayerTanks().values()) {
					if (Math.abs(t.getX() - robot.getX()) < robot.getWidth() / 2 && t.getY() < robot.getY()) { // 如果机器坦克在下面
						boolean ironFlag = false; // 路径中是否有钢铁的标识
						for (Iron iron : resource.getIrons()) { // 子弹路径上，不会有钢铁
							if (Math.abs(iron.getX() - robot.getX()) < iron.getWidth() / 2 && iron.getY() < robot.getY()
									&& iron.getY() > t.getY()) {
								ironFlag = true;
								break;
							}
						}
						if (ironFlag == false) {
							robot.setDirect(Tank.NORTH);
							synchronized (robot.getRemainBulletCount()) {
								if (robot.getRemainBulletCount() > 0) {
									// Bullet bullet = robot.shot();
									// Thread thread = new Thread(new
									// BulletRepaintThread(bullet,
									// robot));
									// thread.start();
								}
							}

						}
					} else if (Math.abs(t.getX() - robot.getX()) < robot.getWidth() / 2 && t.getY() > robot.getY()) { // 如果机器坦克在上面
						boolean ironFlag = false; // 路径中是否有钢铁的标识
						for (Iron iron : resource.getIrons()) { // 子弹路径上，不会有钢铁
							if (Math.abs(iron.getX() - robot.getX()) < iron.getWidth() / 2 && iron.getY() > robot.getY()
									&& iron.getY() < t.getY()) {
								ironFlag = true;
								break;
							}
						}
						if (ironFlag == false) {
							robot.setDirect(Tank.SOUTH);
							synchronized (robot.getRemainBulletCount()) {
								if (robot.getRemainBulletCount() > 0) {
									// Bullet bullet = robot.shot();
									// Thread thread = new Thread(new
									// BulletRepaintThread(bullet,
									// robot));
									// thread.start();
								}
							}
						}
					} else if (Math.abs(t.getY() - robot.getY()) < robot.getWidth() / 2 && t.getX() > robot.getX()) { // 如果机器坦克在左边
						boolean ironFlag = false; // 路径中是否有钢铁的标识
						for (Iron iron : resource.getIrons()) { // 子弹路径上，不会有钢铁
							if (Math.abs(iron.getY() - robot.getY()) < iron.getWidth() / 2 && iron.getX() > robot.getX()
									&& iron.getX() < t.getX()) {
								ironFlag = true;
								break;
							}
						}
						if (ironFlag == false) {
							robot.setDirect(Tank.EAST);
							synchronized (robot.getRemainBulletCount()) {
								if (robot.getRemainBulletCount() > 0) {
									// Bullet bullet = robot.shot();
									// Thread thread = new Thread(new
									// BulletRepaintThread(bullet,
									// robot));
									// thread.start();
								}
							}
						}
					} else if (Math.abs(t.getY() - robot.getY()) < robot.getWidth() / 2 && t.getX() < robot.getX()) { // 如果机器坦克在右边
						boolean ironFlag = false; // 路径中是否有钢铁的标识
						for (Iron iron : resource.getIrons()) { // 子弹路径上，不会有钢铁
							if (Math.abs(iron.getY() - robot.getY()) < iron.getWidth() / 2 && iron.getX() < robot.getX()
									&& iron.getX() > t.getX()) {
								ironFlag = true;
								break;
							}
						}
						if (ironFlag == false) {
							robot.setDirect(Tank.WEST);
							synchronized (robot.getRemainBulletCount()) {
								if (robot.getRemainBulletCount() > 0) {
									// Bullet bullet = robot.shot();
									// Thread thread = new Thread(new
									// BulletRepaintThread(bullet,
									// robot));
									// thread.start();
								}
							}
						}
					}
				}
			}
		}

	}

	/**
	 * 寻路
	 * 
	 * @param startTank
	 * @param endTank
	 */
	public LinkedList<Tank> findRoute(Tank startTank, Tank endTank) {
		Set<Position> closeTable = new HashSet<>(); // closed表
		Comparator<Position> comp = new Comparator<Position>() {

			@Override
			public int compare(Position p1, Position p2) {
				return new Double(p1.getF()).compareTo(new Double(p2.getF()));
			}
		};
		PriorityQueue<Position> opentable = new PriorityQueue<>(comp); // open表

		Position startPosition = new Position(startTank.getX(), startTank.getY()); // 起始点
		Position endPosition = new Position(endTank.getX(), endTank.getY()); // 终点
		startPosition.setDirect(startTank.getDirect());
		startPosition.setH(h(startPosition, endPosition));
		startPosition.setG(0);
		startPosition.setF(h(startPosition, endPosition));
		opentable.add(startPosition);

		int speed = startTank.getSpeed(); // 坦克的移动速度
		boolean finish = false; // 寻路结束的标识
		final int[][] directs = { { 0, -speed }, { 0, speed }, { -speed, 0 }, { speed, 0 } }; // 可以扩展的四个方向
		Position lastPosition = null;
		List<Brick> bricks = resource.getBricks();
		List<Water> waters = resource.getWaters();
		List<Iron> irons = resource.getIrons();
		while (!opentable.isEmpty() && !finish) {
			Position p = opentable.poll(); // 取f最小的节点进行扩展
			closeTable.add(p); // 将已扩展的节点放入closed表
			for (int direct = 0; direct < 4; direct++) { // 判断坦克往四个方向会不会碰到障碍物，如果会碰撞就不进行扩展

				Position newPosition = new Position(p.getX() + directs[direct][0], p.getY() + directs[direct][1]);
				Tank robot1 = new Tank(p.getX(), p.getY(), direct, "");
				// 如果坦克的下一步，没有跑出地图
				if (newPosition.getX() >= 20 && newPosition.getX() <= 600 - 20
						&& newPosition.getY() >= 20 && newPosition.getY() < 600 - 20
						&& !closeTable.contains(newPosition) && !opentable.contains(newPosition)) {
					// 如果已将到达终点,也就是和目标坦克发生碰撞,并且发射子弹能击中终点坦克
					if (robot1.Overlap(endTank)) {
						lastPosition = p;
						// lastPosition.setLast(p);
						finish = true;
						break;
					}
					// 判断robot往direct方向走，会不会碰到砖块、水或者钢铁，如果会碰撞，该direct的下一个坐标就不进行扩展
					for (int j = 0; j < bricks.size(); j++) { // 判断我的坦克是否与砖块重叠
						if (robot1.Overlap(bricks.get(j)) == true) {
							robot1.setCrash(true);
							break;
						}
					}
					for (int j = 0; j < irons.size(); j++) { // 判断我的坦克是否与铁块重叠
						if (robot1.Overlap(irons.get(j)) == true) {
							robot1.setCrash(true);
							break;
						}
					}
					for (int j = 0; j < waters.size(); j++) { // 判断我的坦克是否与河流重叠
						if (robot1.Overlap(waters.get(j)) == true) {
							robot1.setCrash(true);
							break;
						}
					}
					if (robot1.isCrash()) { // 如果坦克在该坐标，该方向的下一个扩展点会发生碰撞，则该扩展点无效
						continue;
					} else {
						newPosition.setDirect(direct);
						newPosition.setLast(p);
						newPosition.setG(p.getG() + speed);
						newPosition.setH(h(newPosition, endPosition));
						newPosition.setF(newPosition.getH() + newPosition.getG());
						opentable.add(newPosition); // 最小的耗散值的节点进入open表
					}
				}
			}
		}
		LinkedList<Tank> list = new LinkedList<>();
		while (lastPosition != null) {
			Tank t = new Tank(lastPosition.getX(), lastPosition.getY(), lastPosition.getDirect(),
					startTank.getTankId());
			list.addFirst(t);
			lastPosition = lastPosition.getLast();
		}
		return list;
	}

	double h(Position pnt, Position endPosition) {
		return hEuclidianDistance(pnt, endPosition);
	}

	/**
	 * 欧式距离,小于等于实际值
	 */
	double hEuclidianDistance(Position endPosition, Tank pnt) {
		return Math.sqrt(Math.pow(pnt.getX() - endPosition.getX(), 2) + Math.pow(pnt.getY() - endPosition.getY(), 2));
	}

	/**
	 * 欧式距离,小于等于实际值
	 */
	double hEuclidianDistance(Tank tank1, Tank tank2) {
		return Math.sqrt(Math.pow(tank1.getX() - tank2.getX(), 2) + Math.pow(tank1.getY() - tank2.getY(), 2));
	}

	/**
	 * 欧式距离,小于等于实际值
	 */
	double hEuclidianDistance(Position pnt, Position endPosition) {
		return Math.sqrt(Math.pow(pnt.getX() - endPosition.getX(), 2) + Math.pow(pnt.getY() - endPosition.getY(), 2));
	}

}
